Skip to content

test: snapshot invoice PDF structure and totals - #1397

Merged
greatest0fallt1me merged 3 commits into
CalloraOrg:mainfrom
Ebomi:security/issue-1301-snapshot-invoice-pdf-structure-and-totals
Oct 1, 2026
Merged

greatest0fallt1me merged 3 commits into
CalloraOrg:mainfrom
Ebomi:security/issue-1301-snapshot-invoice-pdf-structure-and-totals

Conversation

@Ebomi

@Ebomi Ebomi commented Sep 29, 2026

Copy link
Copy Markdown
Contributor

Overview

This PR adds test coverage for generateInvoicePdf in src/services/invoicePdf.ts, which previously built a customer-facing PDF Buffer from InvoicePdfData with no tests. The tests snapshot the PDF structure (header/footer), assert that line item totals are reflected in the output, and cover zero-line-item and special-character edge cases. A small hardening change to the PDF text escaping was needed to satisfy the special-character criterion.

Related Issue

Changes

🧾 Invoice PDF tests

  • [ADD] src/services/invoicePdf.test.ts
    • Asserts the generated buffer starts with the %PDF- header and ends with %%EOF.
    • Asserts the invoice number and computed total appear in the PDF content.
    • Asserts each line item total matches the input (quantity × unit price).
    • Covers the empty line-item list case and asserts a valid PDF is still produced.
    • Covers parentheses and backslashes in API names and asserts the document is not corrupted (header/footer intact, escaped text present, no stray unescaped delimiters).

🛡️ PDF text escaping

  • [MODIFY] src/services/invoicePdf.ts
    • Escapes (, ), and \ in text drawn into the PDF content stream so API names containing these characters cannot break the document structure.
    • No change to the public signature of generateInvoicePdf or to InvoicePdfData; existing callers are unaffected.

Verification Results

npm test -- src/services/invoicePdf.test.ts
✅ all tests passed
Acceptance Criteria Status
Output begins with the PDF header and ends with %%EOF ✅ Asserted in invoicePdf.test.ts
Line item totals match the input ✅ Per-item totals asserted against quantity × unit price
Parentheses and backslashes in names do not corrupt the document ✅ Escaping added in invoicePdf.ts; covered by test
Empty line-item lists still generate a valid PDF ✅ Zero-line-item case asserted to produce header/footer-valid output

Security and Failure Modes

  • Injection into the PDF content stream: Unescaped (, ), or \ in API names could terminate or corrupt a text object. Escaping these characters in invoicePdf.ts prevents malformed output and keeps the document parseable.
  • Empty input: The zero-line-item path is exercised so a missing/empty lineItems array cannot silently produce a broken buffer.
  • No weakened validation: No safeguards were removed; the only production change is additive escaping.

Compatibility

  • generateInvoicePdf signature and InvoicePdfData shape are unchanged.
  • Escaping only affects text rendering for names containing (, ), or \; names without these characters render identically.
  • No dependency or config changes.

Closes #1301

@drips-wave

drips-wave Bot commented Sep 29, 2026

Copy link
Copy Markdown

@Ebomi Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits.

You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀

Learn more about application limits

@greatest0fallt1me
greatest0fallt1me merged commit d79219e into CalloraOrg:main Oct 1, 2026
greatest0fallt1me added a commit to divysam/Callora-Backend that referenced this pull request Oct 1, 2026
Also repair syntax/semantic corruption that landed on main in CalloraOrg#1363, CalloraOrg#1371, CalloraOrg#1397, CalloraOrg#1398
(broken test syntax, deleted rate limiter class, corrupted invoice PDF output,
misspelled config env names, missing await on async apiKeyRepository.create).
greatest0fallt1me added a commit that referenced this pull request Oct 1, 2026
…ystems (#1354)

* docs(shutdown): align graceful-shutdown docs with registered subsystems

Operators size terminationGracePeriodSeconds from docs/graceful-shutdown.md,
but that document advertised a drain set the process never registers: quotas,
proxy, refresh-token and "workers" were all presented as drained while
shutdownSubsystems in src/index.ts only includes six entries, and several
background jobs (plus the quotas/api-keys drain trackers) are never awaited.
Document the exact ordered subsystem list, the 30 s timeoutMs and the 0/1 exit
codes, explain every job that is cancelled rather than drained, correct the
same overstatement in the README and two worker docs, and add a guard test so
the documentation and the wiring cannot drift apart again.

Closes #1344

Generated with Codebuff 🤖
Co-Authored-By: Codebuff <noreply@codebuff.com>

* Merge branch 'main' into fix/graceful-shutdown-docs-1344

Also repair syntax/semantic corruption that landed on main in #1363, #1371, #1397, #1398
(broken test syntax, deleted rate limiter class, corrupted invoice PDF output,
misspelled config env names, missing await on async apiKeyRepository.create).

---------

Co-authored-by: Codebuff <noreply@codebuff.com>
Co-authored-by: greatest0fallt1me <192479186+greatest0fallt1me@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Snapshot invoice PDF structure and totals

2 participants